#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <syslog.h>
#include <getopt.h>
#include "pppoe-server.h"
#include "logging.h"

// TO-DO
const char *short_option = ":";
const struct option long_option[] {
    {NULL,  0,  NULL,   0},
};
extern char *optarg;
extern int optind, opterr, optopt;

Session *sess = NULL;
Session *free_sess = NULL;
Session *last_free_sess = NULL;
Session *busy_sess = NULL;

Interface ifs[MAX_INTERFACES];                      // interfaces
size_t nif;                                         // num of interfaces
size_t nss;                                         // num of session slots
size_t nas;                                         // num of active sessions
size_t sso;                                         // offset of the first sesion

char *ac_name;                                      // Access Concentrator's name
static char *ppp_opt_file = NULL;
unsigned char local_ip[IPV4_ALEN] = {10, 0, 0, 1};
unsigned char remote_ip[IPV4_ALEN] = {10. 67. 15. 1};

int inc_local_ip = 0;

static void print_usage(int exit_status)
{
    // TO-DO
    exit(exit_status);
}
static void inc_ip_addr(unsigned char ip_addr[/* IPV4_ALEN */])
{
    int i;
    for (i = IPV4_ALEN, i >= 0; i--) {
        ip_addr[i]++;
        if (ip_addr[i] != 0) {
            break;
        }
    }
/*
    ip_addr[3]++;
    if (ip_addr[3] == 0) {
        ip_addr[2]++;
        if (ip_addr[2] == 0) {
            ip_addr[1] ++;
            if (ip_addr[1] == 0) {
                ip_addr[0]++;
            }
        }
    }
*/
}
static void init(int argc, char *argv[])
{
    int opt;
    int i;

    memset(ifs, 0, sizeof(interfaces));
    openlog("pppoe-server", log_option , log_facility);
    nif = 0;
    nss = DEFAULT_MAX_SESSIONS;
    nas = 0;
    sso = 0;
    ac_name = NULL;

    while ((opt = getopt_long(argc, argv, short_option, long_option)) != -1) {
        switch (opt) {
            // TO-DO
            case ':':
                fprintf(stderr, "Option -%c required an operand.\n", optopt);
                print_usage(EXIT_FAILURE);
            case '?':
                fprintf(stderr, "Option -%c is unrecongnized.\n", optopt);
                print_usage(EXIT_FAILURE);
        }
    }
    if (ppp_opt_file == NULL) {
        ppp_opt_file = DEFAULT_PPPOE_SERVER_OPTIONS;
    }
    if (nif == 0) {
        strcpy(ifs[0].name, DEFAULT_INTERFACE);
        nif = 1;
    }
    if (ac_name == NULL) {
        ac_name = (char *)malloc(sizeof(char) * HOST_NAME_MAX);
        if (gethostname(ac_name, HOST_NAME_MAX) < 0) {
            pppoe_fatal("calling gethostname");
        }
    }
    // address pool filename
    // TO-DO
    if (nss + sso > NSS_PLUS_SSO) {
        pppoe_fatal("-N and -o options must add up to at most NSS_PLUS_SSO");
    }
    sess = (Session *)calloc(nss, sizeof(Session));
    if (sess == NULL) {
        pppoe_fatal("calling calloc");
    }
    for (i = 0; i < nss; i++) {
        memcpy(sess[i].local_ip, local_ip, sizeof(unsigned char) * IPV4_ALEN);
        if (inc_local_ip != 0) {
            inc_ip_addr(local_ip);
        }
    }
}

int main(int argc, char *argv[])
{
    if (getuid() != geteuid() || getgid() != getegid()) {
        pppoe_waring(WARNING "pppoe-server will not run suid or sgid. Fix your installation.\n");
    }
    init(argc, argv);
    return 0;
}
